{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##统计不同户型，在特定年代范围的二手房平均价格折线分布图##\n",
    "#已知：#\n",
    "* 二手房户型，如：3室2厅2卫\n",
    "* 年代范围，如：1990-2017等\n",
    "#求：#\n",
    "* 不同户型不同年代的房价折线分布图，如：3室2厅2卫的二手房价格在1999，2005，2010年代的平均价格是多少"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Server running in the folder C:\\Users\\Administrator\\Desktop\\ganjiFang at 127.0.0.1:52263\n"
     ]
    }
   ],
   "source": [
    "import pymongo\n",
    "import charts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "client = pymongo.MongoClient('localhost', 27017)\n",
    "ganjiCrawler = client['ganjiCrawler']\n",
    "fangInfo = ganjiCrawler['fangInfo']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# series: [{\n",
    "#         name: '东京',\n",
    "#         data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]\n",
    "#     }, {\n",
    "#         name: '纽约',\n",
    "#         data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]\n",
    "#     }, {\n",
    "#         name: '柏林',\n",
    "#         data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]\n",
    "#     }, {\n",
    "#         name: '伦敦',\n",
    "#         data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]\n",
    "#     }]\n",
    "\n",
    "#Step1：求共有哪几种不同的户型\n",
    "huxingList = [i['huxing'] for i in fangInfo.find()]\n",
    "huxingSetList = list(set(huxingList))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ok\n"
     ]
    }
   ],
   "source": [
    "#更户型数量小于30的，更新为'其他’户型\n",
    "for huxing in huxingSetList:\n",
    "    count = fangInfo.find({'huxing':huxing}).count()\n",
    "    if count < 30:\n",
    "        fangInfo.update_many({'huxing':huxing},{'$set':{'huxing':'其他'}})\n",
    "    else:\n",
    "        pass\n",
    "print('ok')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13\n"
     ]
    }
   ],
   "source": [
    "#统计户型数量，将户型数量少于30的户型归为“其他”户型，得出新的户型列表\n",
    "# def huxingFenLei():\n",
    "#     huxingNewList = []\n",
    "#     for huxing in huxingSetList:\n",
    "#         count = huxingList.count(huxing)\n",
    "#         if count < 30:\n",
    "#             pass\n",
    "#         else:\n",
    "#             huxingNewList.append(huxing)\n",
    "#     huxingNewList.append('其他')\n",
    "#     return huxingNewList\n",
    "\n",
    "# huxingNewList = huxingFenLei()\n",
    "# print(len(huxingNewList))\n",
    "\n",
    "# #更新完户型信息后，重新统计户型种类个数\n",
    "huxingList = [i['huxing'] for i in fangInfo.find()]\n",
    "huxingSetList = list(set(huxingList))\n",
    "print(len(huxingSetList))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ok\n"
     ]
    }
   ],
   "source": [
    "#Step2：统计不同户型，在1990-2017年每年的平均房价\n",
    "\n",
    "#整理更新fangInfo中niandai的数据\n",
    "for i in fangInfo.find():\n",
    "    yearNew = i['niandai'][:4]\n",
    "    fangInfo.update_one({'_id':i['_id']},{'$set':{'niandai':yearNew}})\n",
    "print('ok')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ok\n"
     ]
    }
   ],
   "source": [
    "#更新fangInfo表中price，将其设置为int格式\n",
    "for i in fangInfo.find():\n",
    "    priceNew = int(float(i['price']))\n",
    "    fangInfo.update_one({'_id':i['_id']},{'$set':{'price':priceNew}})\n",
    "print('ok')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#求在1990-2017年中每一年不同户型的平均房价\n",
    "#         {'$group':{'_id':'$niandai', 'avg_price':{'$avg':'$price'}}},\n",
    "#         {'$sort':{'avg_price':1}}\n",
    "def avgPrice(date1, date2, huxing):\n",
    "    pipeline = [\n",
    "        {'$match':{'$and':[{'niandai':{'$gte':date1, '$lte':date2}}, {'huxing':huxing}]}}, \n",
    "        {'$group':{'_id':'$niandai', 'avg_price':{'$avg':'$price'}}},{'$sort':{'_id':1}}]\n",
    "    for i in fangInfo.aggregate(pipeline):\n",
    "        yield i['avg_price']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#根据图表数据结构，生成所有数据\n",
    "def getAllData(date1,date2,huxingList):\n",
    "    series = []\n",
    "    for huxing in huxingList:\n",
    "        data = {\n",
    "            'name':huxing,\n",
    "            'data':[i for i in avgPrice(date1,date2,huxing)]\n",
    "        }\n",
    "        series.append(data)\n",
    "#         print('{}:{}'.format(huxing,len(data['data'])))\n",
    "    return series\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#555;font-family:sans-serif}\n",
       "small{font-weight:400;display:block;font-size:14px}\n",
       "code{background-color:#d3d3d3;border-radius:3px;font-family:monospace;padding:0 .5em}\n",
       ".icon.-facebook:before,.icon.-linkedin:before,.icon.-pinterest:before,.icon.-twitter:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Post-Creator-Icons;font-style:normal;font-variant:normal;font-weight:400;line-height:1;speak:none;text-transform:none}\n",
       "@font-face{font-family:Post-Creator-Icons;src:url(fonts/Post-Creator-Icons.eot);src:url(fonts/Post-Creator-Icons.eot?#iefix) format('embedded-opentype'),url(fonts/Post-Creator-Icons.woff) format('woff'),url(fonts/Post-Creator-Icons.ttf) format('truetype'),url(fonts/Post-Creator-Icons.svg#Post-Creator-Icons) format('svg');font-weight:400;font-style:normal}\n",
       ".icon.-facebook:before{content:\"\\e001\"}\n",
       ".icon.-linkedin:before{content:\"\\e002\"}\n",
       ".icon.-pinterest:before{content:\"\\e003\"}\n",
       ".icon.-twitter:before{content:\"\\e004\"}\n",
       ".social-icons h4{display:inline-block;margin:20px 10px 0 0}\n",
       ".social-icons .icon{display:inline-block;margin:0 5px}\n",
       "body.modal-open{overflow:hidden}\n",
       ".jsoneditor table,.jsoneditor td,.jsoneditor td.tree,.jsoneditor tr{border:none;margin:0}</style>\n",
       "<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.1/css/selectize.default.min.css\"/>\n",
       "<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/4.2.0/jsoneditor.min.css\"/>\n",
       "\n",
       "<div class=\"container-fluid\">\n",
       "    <div class=\"row\">\n",
       "        <div class=\"col-sm-10\">\n",
       "            <input type=\"text\" id=\"variable-selector\">\n",
       "        </div>\n",
       "        <div class=\"col-sm-2\">\n",
       "            <button class=\"btn btn-default pull-right\" type=\"submit\" id=\"settings-button\">Settings</button>\n",
       "        </div>\n",
       "    </div>\n",
       "\n",
       "    <div class=\"row\">\n",
       "        <div class=\"collapse col-xs-12\" id=\"settings-collapse\">\n",
       "            <div class=\"panel panel-default\" style=\"margin-top: 20px\">\n",
       "                <div class=\"panel-heading\"><h3 class=\"panel-title\">Adjust chart settings</h3></div>\n",
       "                <div class=\"panel-body\">\n",
       "                    <div class=\"row\">\n",
       "                        <div id=\"jsoneditor\" class=\"col-md-12\" style=\"height: 350px\"></div>\n",
       "                    </div>\n",
       "                    <div class=\"row\" style=\"margin-top: 10px\">\n",
       "                        <div class=\"col-sm-4\">\n",
       "                            <button type=\"button\" class=\"btn btn-primary\" id=\"save-settings\">\n",
       "                                Apply changes\n",
       "                            </button>\n",
       "                        </div>\n",
       "                        <div class=\"col-sm-8 text-right \">\n",
       "                            <form class=\"form-inline\">\n",
       "                                <div class=\"form-group\">\n",
       "                                    <div class=\"input-group\">\n",
       "                                        <input type=\"text\" class=\"form-control\" id=\"options-input\"\n",
       "                                               placeholder=\"settings\" style=\"text-align: right\">\n",
       "                                        <div class=\"input-group-addon\"><strong>.json</strong></div>\n",
       "                                    </div>\n",
       "                                </div>\n",
       "                                <button type=\"submit\" class=\"btn btn-primary\" id=\"options-button\">Save</button>\n",
       "                            </form>\n",
       "\n",
       "                        </div>\n",
       "                    </div>\n",
       "                </div>\n",
       "            </div>\n",
       "        </div>\n",
       "    </div>\n",
       "\n",
       "    <div class=\"row\">\n",
       "        <div id=\"chart-container\" style=\"min-width: 310px;\"></div>\n",
       "    </div>\n",
       "</div>\n",
       "\n",
       "\n",
       "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js\"></script>\n",
       "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.18/require.min.js\"></script>\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "<script>(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n",
       "//findIndex polyfill\n",
       "if (!Array.prototype.findIndex) {\n",
       "    Array.prototype.findIndex = function(predicate) {\n",
       "        if (this == null) {\n",
       "            throw new TypeError('Array.prototype.findIndex called on null or undefined');\n",
       "        }\n",
       "        if (typeof predicate !== 'function') {\n",
       "            throw new TypeError('predicate must be a function');\n",
       "        }\n",
       "        var list = Object(this);\n",
       "        var length = list.length >>> 0;\n",
       "        var thisArg = arguments[1];\n",
       "        var value;\n",
       "\n",
       "        for (var i = 0; i < length; i++) {\n",
       "            value = list[i];\n",
       "            if (predicate.call(thisArg, value, i, list)) {\n",
       "                return i;\n",
       "            }\n",
       "        }\n",
       "        return -1;\n",
       "    };\n",
       "}\n",
       "\n",
       "if (!Array.prototype.filter) {\n",
       "    Array.prototype.filter = function(fun/*, thisArg*/) {\n",
       "        'use strict';\n",
       "\n",
       "        if (this === void 0 || this === null) {\n",
       "            throw new TypeError();\n",
       "        }\n",
       "\n",
       "        var t = Object(this);\n",
       "        var len = t.length >>> 0;\n",
       "        if (typeof fun !== 'function') {\n",
       "            throw new TypeError();\n",
       "        }\n",
       "\n",
       "        var res = [];\n",
       "        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;\n",
       "        for (var i = 0; i < len; i++) {\n",
       "            if (i in t) {\n",
       "                var val = t[i];\n",
       "\n",
       "                // NOTE: Technically this should Object.defineProperty at\n",
       "                //       the next index, as push can be affected by\n",
       "                //       properties on Object.prototype and Array.prototype.\n",
       "                //       But that method's new, and collisions should be\n",
       "                //       rare, so use the more-compatible alternative.\n",
       "                if (fun.call(thisArg, val, i, t)) {\n",
       "                    res.push(val);\n",
       "                }\n",
       "            }\n",
       "        }\n",
       "\n",
       "        return res;\n",
       "    };\n",
       "}\n",
       "\n",
       "function guid() {\n",
       "    function s4() {\n",
       "        return Math.floor((1 + Math.random()) * 0x10000)\n",
       "            .toString(16)\n",
       "            .substring(1);\n",
       "    }\n",
       "    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +\n",
       "        s4() + '-' + s4() + s4() + s4();\n",
       "}\n",
       "\n",
       "Array.prototype.equals = function (array) {\n",
       "    // if the other array is a false value, return\n",
       "    if (!array)\n",
       "        return false;\n",
       "\n",
       "    // compare lengths - can save a lot of time\n",
       "    if (this.length != array.length)\n",
       "        return false;\n",
       "\n",
       "    for (var i = 0, l = this.length; i < l; i++) {\n",
       "        // Check if we have nested arrays\n",
       "        if (this[i] instanceof Array && array[i] instanceof Array) {\n",
       "            // recurse into the nested arrays\n",
       "            if (!this[i].equals(array[i]))\n",
       "                return false;\n",
       "        }\n",
       "        else if (this[i] != array[i]) {\n",
       "            // Warning - two different object instances will never be equal: {x:20} != {x:20}\n",
       "            return false;\n",
       "        }\n",
       "    }\n",
       "    return true;\n",
       "};\n",
       "\n",
       "},{}]},{},[1]);\n",
       "</script>\n",
       "<script>(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n",
       "\n",
       "\n",
       "requirejs.config({\n",
       "    \"paths\": {\n",
       "        \"highstock\": \"https://cdnjs.cloudflare.com/ajax/libs/highstock/2.1.5/highstock\",\n",
       "        \"export\": \"https://cdnjs.cloudflare.com/ajax/libs/highstock/2.1.5/modules/exporting\",\n",
       "        \"more\": \"https://cdnjs.cloudflare.com/ajax/libs/highstock/2.1.7/highcharts-more\",\n",
       "        \"jsoneditor\": \"https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/4.2.0/jsoneditor.min\",\n",
       "        \"selectize\": \"https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.1/js/standalone/selectize.min\",\n",
       "        \"jquery\": \"https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min\"\n",
       "    },\n",
       "    \"shim\": {\n",
       "        \"export\": [\"highstock\"],\n",
       "        \"more\": [\"highstock\"]\n",
       "    }\n",
       "});\n",
       "\n",
       "//Define jquery here to use the pre-loaded version\n",
       "define('jquery', [], function() {\n",
       "    return jQuery;\n",
       "});\n",
       "\n",
       "},{}]},{},[1]);\n",
       "</script>\n",
       "<script>(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n",
       "//Count the number of charts on the page\n",
       "if (window.counter == undefined) {\n",
       "    window.counter = 0;\n",
       "} else {\n",
       "    window.counter++;\n",
       "}\n",
       "\n",
       "requirejs([\n",
       "    'jquery',\n",
       "    'selectize',\n",
       "    'jsoneditor',\n",
       "    'highstock',\n",
       "    'export',\n",
       "    'more'\n",
       "], function ($, selectize, JSONEditor) {\n",
       "\n",
       "    function guid() {\n",
       "        function s4() {\n",
       "            return Math.floor((1 + Math.random()) * 0x10000)\n",
       "                .toString(16)\n",
       "                .substring(1);\n",
       "        }\n",
       "\n",
       "        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +\n",
       "            s4() + '-' + s4() + s4() + s4();\n",
       "    }\n",
       "\n",
       "    var id = guid();\n",
       "    plot(id);\n",
       "\n",
       "    function plot(id) {\n",
       "        var series = [\n",
       "            {data: [1, 2, 4, 9], name: \"temperature 1\", display: true, color: '#2b908f'},\n",
       "            {data: [9, 4, 2, 1], name: \"temperature 2\", display: true},\n",
       "            {data: [0, 3, 5, 6], name: \"temperature 3\", display: false}\n",
       "        ];\n",
       "        var series = [{\"name\": \"4\\u5ba42\\u53853\\u536b\", \"data\": [345.0, 165.0, 450.0, 380.0, 647.2, 312.0, 850.0, 385.0, 665.0, 771.6, 1245.7142857142858, 1750.0, 662.4, 888.0, 1828.0, 1012.0, 394.0, 1323.3333333333333, 275.0, 308.5], \"display\": true}, {\"name\": \"1\\u5ba41\\u53851\\u536b\", \"data\": [132.66666666666666, 175.0, 180.14285714285714, 150.0, 80.0, 127.0, 110.3, 115.0, 137.45454545454547, 159.45454545454547, 155.375, 72.5, 162.14285714285714, 187.66666666666666, 134.0, 133.72727272727272, 249.22222222222223, 174.8, 184.5, 147.68421052631578, 143.73684210526315, 87.6, 84.40625, 54.02857142857143, 62.44186046511628, 72.11666666666666, 60.18681318681319, 54.017857142857146], \"display\": true}, {\"name\": \"5\\u5ba42\\u53853\\u536b\", \"data\": [350.0, 830.0, 1280.0, 840.0, 790.0, 950.0, 1060.0, 677.5, 2500.0, 742.5, 1810.0, 860.0, 855.0, 876.25, 420.0, 377.5, 570.0, 2988.0, 4019.0, 550.0], \"display\": true}, {\"name\": \"3\\u5ba41\\u53852\\u536b\", \"data\": [440.0, 245.0, 370.0, 226.0, 310.4, 315.0, 335.0, 200.0, 298.3333333333333, 270.0, 553.3333333333334, 925.0, 520.0, 271.5, 331.0, 160.0, 485.0, 221.0, 60.0, 85.5, 87.28571428571429], \"display\": true}, {\"name\": \"3\\u5ba42\\u53852\\u536b\", \"data\": [780.0, 503.0, 430.0, 511.4, 291.22222222222223, 254.4, 273.38461538461536, 306.7142857142857, 360.7916666666667, 354.04761904761904, 322.258064516129, 383.2894736842105, 319.55357142857144, 408.09375, 351.625, 388.6896551724138, 434.0833333333333, 394.6835443037975, 328.2, 293.03370786516854, 239.45238095238096, 230.4915254237288, 214.72881355932202, 241.0, 212.63235294117646, 123.29166666666667, 167.2127659574468], \"display\": true}, {\"name\": \"2\\u5ba42\\u53851\\u536b\", \"data\": [261.22222222222223, 120.0, 271.0, 164.66666666666666, 271.5, 193.8913043478261, 188.1764705882353, 204.3, 178.28571428571428, 182.2127659574468, 258.5897435897436, 258.1923076923077, 331.53125, 236.94285714285715, 302.71794871794873, 312.8636363636364, 280.3421052631579, 349.9, 286.6216216216216, 251.10526315789474, 188.33333333333334, 189.35714285714286, 173.78048780487805, 176.36, 180.33333333333334, 105.71428571428571, 129.02702702702703, 126.3], \"display\": true}, {\"name\": \"2\\u5ba41\\u53851\\u536b\", \"data\": [207.77777777777777, 195.0, 232.15384615384616, 192.07142857142858, 200.4, 187.91935483870967, 151.55172413793105, 167.17777777777778, 187.02898550724638, 195.04, 221.2153846153846, 227.6153846153846, 260.3529411764706, 246.45454545454547, 221.05, 247.58333333333334, 307.70588235294116, 218.46153846153845, 289.7826086956522, 114.72727272727273, 202.27777777777777, 199.25, 164.35294117647058, 187.47058823529412, 110.60714285714286, 95.86206896551724, 99.0, 108.28571428571429], \"display\": true}, {\"name\": \"2\\u5ba42\\u53852\\u536b\", \"data\": [320.0, 130.0, 318.0, 285.0, 414.0, 168.0, 214.85714285714286, 323.3333333333333, 580.0, 562.5, 232.66666666666666, 379.3333333333333, 324.0, 106.875, 89.5, 111.0, 155.0, 50.5, 85.0], \"display\": true}, {\"name\": \"4\\u5ba42\\u53851\\u536b\", \"data\": [420.0, 600.0, 559.3333333333334, 662.6666666666666, 160.0, 134.0, 636.6666666666666, 850.0, 426.0, 250.0, 597.5, 195.0, 346.0, 305.0, 436.0, 28.0], \"display\": true}, {\"name\": \"\\u5176\\u4ed6\", \"data\": [174.0, 541.2, 97.5, 416.0, 248.0, 467.0, 223.0, 1417.8181818181818, 736.25, 685.7, 840.6875, 1798.2105263157894, 805.5454545454545, 530.2666666666667, 453.57142857142856, 1340.3333333333333, 853.0, 2688.4444444444443, 539.8571428571429, 1492.4074074074074, 1055.4545454545455, 687.2142857142857, 274.2083333333333, 958.4736842105264, 792.3125], \"display\": true}, {\"name\": \"3\\u5ba42\\u53851\\u536b\", \"data\": [392.1111111111111, 390.5, 274.9, 262.0, 262.02564102564105, 302.5882352941176, 282.76, 238.9787234042553, 219.975, 320.6363636363636, 287.51851851851853, 278.6060606060606, 342.8709677419355, 338.72222222222223, 331.22222222222223, 352.53846153846155, 409.1666666666667, 327.3921568627451, 244.77777777777777, 277.0689655172414, 332.8, 196.6046511627907, 217.74193548387098, 252.23809523809524, 153.9298245614035, 139.72413793103448, 141.31578947368422], \"display\": true}, {\"name\": \"3\\u5ba41\\u53851\\u536b\", \"data\": [261.5, 510.0, 485.0, 313.0, 152.25, 251.86666666666667, 217.85714285714286, 259.3076923076923, 243.92307692307693, 265.4736842105263, 279.55172413793105, 297.375, 238.88888888888889, 355.0, 278.05882352941177, 286.93333333333334, 392.42857142857144, 271.5, 275.0625, 493.5, 297.1, 250.85714285714286, 191.16666666666666, 196.14285714285714, 152.71428571428572, 67.5, 242.0], \"display\": true}, {\"name\": \"4\\u5ba42\\u53852\\u536b\", \"data\": [690.0, 730.0, 512.0, 562.5, 468.6, 382.6666666666667, 456.14285714285717, 509.09090909090907, 580.8333333333334, 482.7142857142857, 723.6, 528.8888888888889, 495.6190476190476, 504.44444444444446, 680.7142857142857, 700.6551724137931, 381.7857142857143, 471.8333333333333, 477.8888888888889, 296.45454545454544, 335.42857142857144, 358.3157894736842, 240.04545454545453, 364.3333333333333, 290.0], \"display\": true}]\n",
       "        var options = {};\n",
       "        var options = {\"width\": \"auto\", \"height\": 400, \"scale\": 2, \"type\": \"line\", \"chart\": {\"zoomType\": \"xy\", \"type\": \"line\"}, \"title\": {\"text\": \"\\u5e7f\\u5dde\\u5404\\u6237\\u578b\\u4e8c\\u624b\\u623f\\u57281990-2017\\u5e74\\u7684\\u5e73\\u5747\\u4ef7\\u683c\\u53d8\\u5316\\u56fe\"}, \"xAxis\": {\"categories\": [\"1990\", \"1991\", \"1992\", \"1993\", \"1994\", \"1995\", \"1996\", \"1997\", \"1998\", \"1999\", \"2000\", \"2001\", \"2002\", \"2003\", \"2004\", \"2005\", \"2006\", \"2007\", \"2008\", \"2009\", \"2010\", \"2011\", \"2012\", \"2013\", \"2014\", \"2015\", \"2016\", \"2017\"], \"title\": {\"text\": \"\\u5e74\\u4ee3\"}}, \"yAxis\": {\"title\": {\"text\": \"\\u4ef7\\u683c\\uff08\\u4e07\\u5143\\uff09\"}, \"min\": 0}, \"plotOptions\": {\"line\": {\"dataLabels\": {\"enabled\": \"true\", \"color\": \"#000000\"}}}}\n",
       "        var useHighStock = false;\n",
       "        var useHighStock = false\n",
       "        var save = 'app/chart.svg';\n",
       "        var save = false\n",
       "        var url = 'http://127.0.0.1:65079';\n",
       "        var url = \"http://127.0.0.1:52263/\"\n",
       "        var settingsFile = 'settings';\n",
       "        var settingsFile = \"settings\"\n",
       "        var scale = options.scale;\n",
       "\n",
       "        //Create different containers for the charts\n",
       "        var chartContainer = document.getElementById(\"chart-container\");\n",
       "        chartContainer.id = \"chart-container\" + id;\n",
       "        chartContainer.style.height = options.height.toString() + 'px';\n",
       "\n",
       "        if (options.width != 'auto') {\n",
       "            chartContainer.style.width = options.width.toString() + 'px';\n",
       "        }\n",
       "\n",
       "        var selector = $(\"#variable-selector\");\n",
       "        selector.attr('id', \"variable-selector\" + id);\n",
       "\n",
       "        var settings = $(\"#settings-collapse\");\n",
       "        settings.attr('id', \"settings-collapse\" + id);\n",
       "\n",
       "        var button = $(\"#settings-button\");\n",
       "        button.attr('id', \"settings-button\" + id);\n",
       "\n",
       "        var saveButton = $(\"#save-settings\");\n",
       "        saveButton.attr('id', \"save-settings\" + id);\n",
       "\n",
       "        var optionsInput = $(\"#options-input\");\n",
       "        optionsInput.attr('id', \"options-input\" + id);\n",
       "        optionsInput.val(settingsFile);\n",
       "\n",
       "        var optionsButton = $(\"#options-button\");\n",
       "        optionsButton.attr('id', \"options-button\" + id);\n",
       "\n",
       "        // create the editor\n",
       "        var editorContainer = document.getElementById(\"jsoneditor\");\n",
       "        editorContainer.id = \"jsoneditor\" + id;\n",
       "        var editor = new JSONEditor(editorContainer);\n",
       "\n",
       "        button.on('click', showSettings);\n",
       "        saveButton.on('click', applyOptions);\n",
       "        optionsButton.on('click', saveOptions);\n",
       "\n",
       "        function applyOptions() {\n",
       "            var newOptions = editor.get();\n",
       "            setOptions(newOptions);\n",
       "            settings.collapse('hide');\n",
       "        }\n",
       "\n",
       "        function saveOptions(event) {\n",
       "            event.preventDefault();\n",
       "\n",
       "            applyOptions();\n",
       "\n",
       "            var options = chart.options;\n",
       "            delete options.exporting;\n",
       "\n",
       "            var name = optionsInput.val() ? optionsInput.val() + '.json' : 'settings.json';\n",
       "\n",
       "            options['settingsFile'] = name;\n",
       "\n",
       "            $.ajax({\n",
       "                type: \"POST\",\n",
       "                url: url,\n",
       "                data: JSON.stringify({\n",
       "                    options: options,\n",
       "                    name: name\n",
       "                })\n",
       "            });\n",
       "        }\n",
       "\n",
       "        function showSettings() {\n",
       "            settings.collapse('toggle');\n",
       "        }\n",
       "\n",
       "        //Choose a chart type\n",
       "        var ChartType = useHighStock ? Highcharts.StockChart : Highcharts.Chart;\n",
       "\n",
       "        //Default highchart colors\n",
       "        var colors = ['#7cb5ec', '#434348', '#90ed7d', '#f7a35c', '#8085e9',\n",
       "            '#f15c80', '#e4d354', '#2b908f', '#f45b5b', '#91e8e1'];\n",
       "\n",
       "        series.map(function (serie, index) {\n",
       "            if (!serie.color) {\n",
       "                serie['color'] = colors[index % 10];\n",
       "            }\n",
       "\n",
       "            return serie;\n",
       "        });\n",
       "\n",
       "        //Get all the keys\n",
       "        var keys = [];\n",
       "        var initialKeys = [];\n",
       "        $.each(series, function (index, serie) {\n",
       "            keys.push({\n",
       "                display: serie.display,\n",
       "                value: serie.name,\n",
       "                text: serie.name\n",
       "            });\n",
       "\n",
       "            if (serie.display) {\n",
       "                initialKeys.push(serie.name)\n",
       "            }\n",
       "        });\n",
       "\n",
       "        selector.selectize({\n",
       "            plugins: ['remove_button', 'restore_on_backspace'],\n",
       "            delimiter: ',',\n",
       "            options: keys,\n",
       "            items: initialKeys,\n",
       "            onItemAdd: function (key) {\n",
       "                console.log('series added');\n",
       "                addSeries(key);\n",
       "                newChart(chart.options, renderedSeries);\n",
       "            },\n",
       "            onItemRemove: function (key) {\n",
       "                console.log('series removed');\n",
       "                deleteSeries(key);\n",
       "                newChart(chart.options, renderedSeries);\n",
       "            }\n",
       "        });\n",
       "\n",
       "        //Set initial chart options\n",
       "        var chartOptions;\n",
       "        if (typeof options.chart === \"undefined\") {\n",
       "            chartOptions = {renderTo: chartContainer.id};\n",
       "        } else {\n",
       "            chartOptions = $.extend(options[\"chart\"], {renderTo: chartContainer.id});\n",
       "        }\n",
       "\n",
       "        //Initial rendered series\n",
       "        var renderedSeries = [];\n",
       "        options = $.extend(options, {chart: chartOptions}, {series: renderedSeries});\n",
       "        var chart = new ChartType(options);\n",
       "\n",
       "        $.each(initialKeys, function (index, key) {\n",
       "            addSeries(key);\n",
       "        });\n",
       "\n",
       "        newChart(chart.options, renderedSeries);\n",
       "        editor.set(chart.options);\n",
       "\n",
       "        if (save) {\n",
       "            saveSVG(url, save)\n",
       "        }\n",
       "\n",
       "        function setOptions(options) {\n",
       "            //Prevent export from breaking\n",
       "            delete options.exporting;\n",
       "            options['exporting'] = {scale: options.scale};\n",
       "\n",
       "            chartContainer.style.height = options.height.toString() + 'px';\n",
       "\n",
       "            if (options.width != 'auto') {\n",
       "                chartContainer.style.width = options.width.toString() + 'px';\n",
       "            }\n",
       "\n",
       "            newChart(options, renderedSeries);\n",
       "\n",
       "        }\n",
       "\n",
       "        function findSeries(series, key) {\n",
       "            return series.findIndex(function (obj) {\n",
       "                return obj.name == key;\n",
       "            })\n",
       "        }\n",
       "\n",
       "        function newChart(options, series) {\n",
       "            //Disable animation\n",
       "            var newOptions = $.extend(options, {series: series});\n",
       "            newOptions.plotOptions['series'] = {animation: false};\n",
       "\n",
       "            //Get zoom\n",
       "            var xExtremes = chart.xAxis[0].getExtremes();\n",
       "\n",
       "            //Re-plot the chart\n",
       "            chart.destroy();\n",
       "            chart = new ChartType(newOptions);\n",
       "\n",
       "            //Reset the zoom\n",
       "            chart.xAxis[0].setExtremes(xExtremes.min, xExtremes.max, false, false);\n",
       "\n",
       "            //Re-draw chart\n",
       "            chart.redraw();\n",
       "        }\n",
       "\n",
       "        function addSeries(key) {\n",
       "            var index = findSeries(series, key);\n",
       "            var newSeries = series[index];\n",
       "            renderedSeries.push(newSeries)\n",
       "        }\n",
       "\n",
       "        function deleteSeries(key) {\n",
       "            var index = findSeries(renderedSeries, key);\n",
       "            renderedSeries.splice(index, 1)\n",
       "        }\n",
       "\n",
       "        function saveSVG(url, name) {\n",
       "            $.ajax({\n",
       "                type: \"POST\",\n",
       "                url: url,\n",
       "                data: JSON.stringify({\n",
       "                    svg: chart.getSVG(),\n",
       "                    name: name\n",
       "                })\n",
       "            });\n",
       "        }\n",
       "\n",
       "        console.log('loaded!', Date());\n",
       "    }\n",
       "\n",
       "});\n",
       "\n",
       "},{}]},{},[1]);\n",
       "</script>\n",
       "\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "options = {\n",
    "    'chart':{'zoomType':'xy'},\n",
    "    'title':{'text':'广州各户型二手房在1990-2017年的平均价格变化图'},\n",
    "    'xAxis':{'categories':[str(i) for i in range(1990,2018)],'title':{'text':'年代'}},\n",
    "    'yAxis':{'title':{'text':'价格（万元）'}, 'min':0},\n",
    "    'plotOptions':{'line':{'dataLabels':{'enabled':'true', 'color':'#000000'}}}\n",
    "}\n",
    "\n",
    "series = getAllData('1990', '2017', huxingSetList)\n",
    "\n",
    "charts.plot(series, show='inline', options=options)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
